#include "DDS_AD9833.h"		// AD9833 definitions.

#define RealFreDat    268435456.0/AD9833_FCLK//总的公式为 Fout=（Fclk/2的28次方）*28位寄存器的值

/******************************************************************************/
/* Registers */

#define AD9833_REG_CMD    0x0000
#define AD9833_REG_FREQ0  0x4000
#define AD9833_REG_FREQ1  0x8000
#define AD9833_REG_PHASE0 0x6000
#define AD9833_REG_PHASE1 0x7000

/* 命令控制位定义 */
#define AD9833_B28          0x2000
#define AD9833_HLB          0x1000
#define AD9833_FSEL0        0x0000
#define AD9833_FSEL1        0x0800
#define AD9833_PSEL0        0x0000
#define AD9833_PSEL1        0x0400
#define AD9833_PIN_SW       0x0200
#define AD9833_RESET        0x0100
#define AD9833_SLEEP1       0x0080
#define AD9833_SLEEP12      0x0040
#define AD9833_OPBITEN      0x0020
#define AD9833_SIGN_PIB     0x0010
#define AD9833_DIV2         0x0008
#define AD9833_MODE         0x0002

#define AD9833_OUT_SINUS    0x0000
#define AD9833_OUT_TRIANGLE 0x0002
#define AD9833_OUT_MSB      0x0028
#define AD9833_OUT_MSB2     0x0020
/******************************************************************************/
static uint16_t AD9833_REG_Value= 0;
static AD9833_Typedf* AD9833_Pointer;

#define AD9833_CS(x)      //如果有CS就在这里添加
///////////////////////高速读写寄存器操作//////////////////////////
#define AD9833_SDATA(x)   if(x)AD9833_Pointer->GPIOSDA->BSRR = (uint32_t)AD9833_Pointer->SDA;\
						  else AD9833_Pointer->GPIOSDA->BRR = (uint32_t)AD9833_Pointer->SDA;
#define AD9833_SCLK(x)    if(x)AD9833_Pointer->GPIOSCL->BSRR = (uint32_t)AD9833_Pointer->SCL;\
		                  else AD9833_Pointer->GPIOSCL->BRR = (uint32_t)AD9833_Pointer->SCL;
#define AD9833_FSYNC(x)   if(x)AD9833_Pointer->GPIOFSYNC->BSRR = (uint32_t)AD9833_Pointer->FSYNC;\
					      else AD9833_Pointer->GPIOFSYNC->BRR = (uint32_t)AD9833_Pointer->FSYNC;

/////////////////////Static声明的函数为隐藏函数，你没必要看//////////////////////
static void AD9833_SetRegisterValue(uint16_t regValue)
{
    AD9833_SCLK(1);
    AD9833_FSYNC(0);
    AD9833_CS(0);

    for (int8_t i = 15; i >= 0; i--) {
        AD9833_SDATA((regValue >> i) & 1);
        AD9833_SCLK(0);
        AD9833_SCLK(1);
    }

    AD9833_CS(1);
    AD9833_SDATA(1);
    AD9833_FSYNC(1);
}
/////////////////////Static声明的函数为隐藏函数，你没必要看//////////////////////


void AD9833_Init(AD9833_Typedf* this,
		GPIO_TypeDef  *GPIOSCL,uint16_t SCL,
		GPIO_TypeDef  *GPIOSDA,uint16_t SDA,
		GPIO_TypeDef  *GPIOFSYNC,uint16_t FSYNC,
		AD9833_Type type)
{
	this->GPIOSCL = GPIOSCL;
	this->GPIOSDA = GPIOSDA;
	this->GPIOFSYNC = GPIOFSYNC;
	this->SCL = SCL;
	this->SDA = SDA;
	this->FSYNC = FSYNC;
	AD9833_Pointer = this;//设置全局指针
	//如果使用CubeMX配置则不需要以下代码
    ////////////////////////////////-->>>>>>>>>>>>
	GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    GPIO_InitStruct.Pin = SCL;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出模式
    GPIO_InitStruct.Pull = GPIO_NOPULL;        // 无上下拉
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; // 高速(如果是F103可能会报错，请删除或者改掉)
    HAL_GPIO_Init(GPIOSCL, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = SDA;
    HAL_GPIO_Init(GPIOSDA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = FSYNC;
    HAL_GPIO_Init(GPIOFSYNC, &GPIO_InitStruct);
    ////////////////////////////////-->>>>>>>>>>>>

    AD9833_SetRegisterValue(AD9833_REG_CMD | AD9833_RESET);
    for(int i = 0;i<10000;i++);//延时,等待
    AD9833_SetWave(this,type);
}

/*
reg:通道选择
fout:输出频率
*/
void AD9833_SetFrequency(AD9833_Typedf* this,uint8_t reg, float freq)
{
    unsigned long val = RealFreDat * freq;
    AD9833_Pointer = this;
    AD9833_SetRegisterValue(AD9833_B28|AD9833_REG_Value); // 启用B28模式并且保存之前的设置值
    if(reg){
        AD9833_SetRegisterValue(AD9833_REG_FREQ1 | (val & 0x3FFF));  // 写入低位
        AD9833_SetRegisterValue(AD9833_REG_FREQ1 | ((val & 0xFFFC000) >> 14));  // 写入高位
    }else{
    	AD9833_SetRegisterValue(AD9833_REG_FREQ0 | (val & 0x3FFF));  // 写入低位
    	AD9833_SetRegisterValue(AD9833_REG_FREQ0 | ((val & 0xFFFC000) >> 14));  // 写入高位
    }
}

/*
Phasereg:相位寄存器选择
val:相位0~4095
*/
void AD9833_SetPhase(AD9833_Typedf* this,uint8_t Phasereg, uint16_t val)
{
    // 确保相位值在有效范围内 (0-4095)
    if (val > 0xFFF) val = 0xFFF;
    AD9833_Pointer = this;
    // 临时保存当前频率选择位
    uint16_t freq_select = 0;
    if (Phasereg == 0) freq_select = AD9833_FSEL0;
    else freq_select = AD9833_FSEL1;

    // 清除B28位以确保相位设置不会影响频率
    uint16_t control = freq_select;
    AD9833_SetRegisterValue(control);

    // 选择性写入相位寄存器
    uint16_t phase_reg;
    if(Phasereg == 0) phase_reg = AD9833_REG_PHASE0;
    else phase_reg = AD9833_REG_PHASE1;

    // 写入相位值
    AD9833_SetRegisterValue(phase_reg | (val & 0xFFF));
}


void AD9833_SetWave(AD9833_Typedf* this,AD9833_Type type) {
    // 清除波形相关位，保留其他控制位
    AD9833_REG_Value &= ~(AD9833_MODE | AD9833_SIGN_PIB | AD9833_DIV2 | AD9833_OPBITEN);
    AD9833_Pointer = this;//重新设置全局指针

    switch (type) {// 根据波形类型设置相应位
        case AD9833_Type_Sin:
            break;
        case AD9833_Type_triangle:
            AD9833_REG_Value |= AD9833_MODE;
            break;
        case AD9833_Type_rectangle:
            AD9833_REG_Value |= AD9833_OPBITEN | AD9833_DIV2;
            break;
    }
    // 写入更新后的控制寄存器值
    AD9833_SetRegisterValue(AD9833_REG_Value);
}
/*Min_freq：开始频率
 * Max_freq:结束频率
 * step：步进
 * time：总时间
 * */
void AD9833_SweepWave_block(AD9833_Typedf* this,float Min_freq, float Max_freq,float step,uint16_t time){
	AD9833_Pointer = this;//重新设置全局指针
	float freq = Min_freq;
	for(;freq<Max_freq;freq += step){
		AD9833_SetFrequency(this,0,freq);
		if(time!=0)
			HAL_Delay(time);
	}
	for(freq = Max_freq;freq>Min_freq;freq -= step){
		AD9833_SetFrequency(this,0,freq);
		if(time!=0)
			HAL_Delay(time);
	}
}

/*Min_freq：开始频率
 * Max_freq:结束频率
 * step：步进
 * time：总时间
 * */
void AD9833_SweepWave(AD9833_Typedf* this,float Min_freq, float Max_freq,float step,uint16_t time){
	AD9833_Pointer = this;//重新设置全局指针
	static float freq;
	static uint8_t once_flag;
	if(once_flag){
		once_flag = 0;
		freq = Min_freq;
	}
	static uint8_t dir_flag = 1;//为0的时候是递增。
	AD9833_SetFrequency(this,0,freq);
	if(dir_flag){//递增
		freq += step;
	}else{//递减
		freq -= step;
	}

	if(freq>=Max_freq){
		dir_flag = 0;
	}else if(freq<= Min_freq){
		dir_flag = 1;
	}
	if(time!=0)
		HAL_Delay(time);
}


void AD9833_Sleep(AD9833_Typedf* this){
  AD9833_Pointer = this;//重新设置全局指针
  AD9833_SetRegisterValue(0xC0);//禁用时钟和DAC
}

void AD9833_ReSet(AD9833_Typedf* this){
  AD9833_Pointer = this;//重新设置全局指针
  AD9833_SetRegisterValue(0x0000 | 0x0100);
}
